package com.mxx.common.http;

import com.mxx.common.utils.InputStreamUtil;
import com.mxx.common.conv.JsonUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author itzgyw
 * @Date 2020-01-30
 * @Time 23:23
 * @Description:
 */
@Slf4j
@Getter
public class ApacheHttpResponse implements com.mxx.common.http.HttpResponse {
    private int statusCode;
    private String contentType;
    private long len;
    private Map<String, String> headerElements;
    private byte[] bytes;
    private Charset charset;

    public static ApacheHttpResponse read(HttpResponse response) throws com.mxx.common.exception.IOException {
        return new ApacheHttpResponse(response);
    }

    private ApacheHttpResponse(HttpResponse response) throws com.mxx.common.exception.IOException {
        StatusLine statusLine = response.getStatusLine();
        HttpEntity httpEntity = response.getEntity();
        Header[] headerArray = response.getAllHeaders();

        this.statusCode = statusLine.getStatusCode();
        this.len = httpEntity.getContentLength();
        this.headerElements = new HashMap<>();
        for (Header header : headerArray) {
            headerElements.put(header.getName(), header.getValue());
        }
        this.contentType = headerElements.get("Content-Type");
        try (InputStream inputStream = httpEntity.getContent()) {
            this.charset = getCharset(contentType);
            this.bytes = InputStreamUtil.readBytes(inputStream);
        } catch (IOException ex) {
            throw new com.mxx.common.exception.IOException(ex, "ApacheHttpResponse.read failure");
        }
    }

    private Charset getCharset(String contentType) {
        try {
            if (contentType == null) {
                return StandardCharsets.UTF_8;
            }
            int index;
            String charsetStr;
            if (contentType != null && (index = contentType.indexOf("charset")) != -1) {
                charsetStr = contentType.substring(index + 8);
                return Charset.forName(charsetStr.trim());
            }
        } catch (Exception ex) {
        }
        return StandardCharsets.UTF_8;
    }

    @Override
    public long getContentLength() {
        return this.len;
    }

    @Override
    public Charset getCharset() {
        return this.charset;
    }

    @Override
    public boolean isSuccessful() {
        return this.statusCode == 200;
    }

    @Override
    public String getBody() {
        return new String(this.bytes, this.charset);
    }

    @Override
    public Map toJson() {
        return JsonUtil.toJSON(this.getBody());
    }

    @Override
    public <T> T toEntity(Class<T> classes) {
        return JsonUtil.toJSON(this.getBody()).toJavaObject(classes);
    }

    @Override
    public byte[] getByte() {
        return this.bytes;
    }

    @Override
    public int statusCode() {
        return this.statusCode;
    }

    @Override
    public String getHeader(String headerName) {
        return this.headerElements.get(headerName);
    }

}
